`default_nettype none

module DecoderTestbed (clkin, dout, hi_in, hi_out, hi_inout, hi_muxsel, i2c_sda, i2c_scl);

input wire			clkin; // 166MHz input clock
output wire			dout; // serial data out

// Opal-Kelly Host Interface - USB chip connection
input	wire [7:0]	hi_in;
output	wire [1:0]	hi_out;
inout	wire [15:0]	hi_inout;
output	wire		hi_muxsel;
output	wire		i2c_sda;
output	wire		i2c_scl;

assign hi_muxsel = 1'b0;
assign i2c_sda = 1'bz;
assign i2c_scl = 1'bz;

// Opal Kelly Host Interface internal connections
parameter N = 1;
wire			ti_clk;
wire [30:0]		ok1;
wire [16:0]		ok2;
wire [17*N-1:0]	ok2x;

// DCM clocks
wire	clk1x; // 12ns (83.3MHz) DCM clock
wire	clk2x; // 6ns (166MHz) DCM clock
wire	clk4x; // 3ns (333MHz) DCM clock

wire	clk1xdcm;
wire	clk2xdcm;
wire	clk4xdcm;

// FIFO
wire			wr_en;
wire			rd_en;
wire [63:0]		fifo_dout;
wire			fifo_empty;

// pipe
wire [15:0]		pipe_dout;

// parallel data
wire [31:0]	dec_out;

// Opal Kelly Host
okHost okHI	(	.hi_in( hi_in ),
				.hi_out( hi_out ),
				.hi_inout( hi_inout ),
				.ti_clk( ti_clk ),
				.ok1( ok1 ),
				.ok2( ok2 )
			);
   
// Opal Kelly output multiplexer
okWireOR #(.N(N)) wireOR ( ok2, ok2x );        // N = 3: 1 x okBTPipeOut pipe, 2 x okWireOut
   
// Opal Kelly pipe from PC
okBTPipeIn pipe (
	.ok1( ok1 ),
	.ok2( ok2x[ 0*17 +: 17 ] ),
	.ep_addr( 8'h9c ),
	.ep_dataout( pipe_dout ),
	.ep_write( wr_en ),
	.ep_blockstrobe(  ),
	.ep_ready( fifo_empty ));

fifo16x1024x64 fifo (
	.rst( 1'b0 ),
	.wr_clk( ti_clk ),
	.rd_clk( clk1x ),
	.din( pipe_dout ),
	.wr_en( wr_en ),
	.rd_en( rd_en ),
	.dout( fifo_dout ),
	.full(  ),
	.empty( fifo_empty ) );

DCM_SP #(
	.CLK_FEEDBACK 	("1X"),
	.CLKDV_DIVIDE	(2.0),
	.CLKIN_PERIOD	("6.0"),
	.DESKEW_ADJUST	("0"),	
	.CLKFX_MULTIPLY	(2),
	.CLKFX_DIVIDE	(1))	
dcm_clk (
	.CLKIN   	(clkin),
	.CLKFB   	(clk2x),
	.DSSEN 		(1'b0),
	.PSINCDEC	(1'b0),
	.PSEN 		(1'b0),
	.PSCLK 		(1'b0),
	.RST     	(1'b0),
	.CLK0    	(clk2xdcm),
	.CLK90   	(),
	.CLK180  	(),
	.CLK270  	(),
	.CLK2X   	(),
	.CLK2X180	(),
	.CLKDV   	(clk1xdcm),
	.CLKFX   	(clk4xdcm),
	.CLKFX180	(),
	.LOCKED  	(),
	.PSDONE  	(),
	.STATUS  	());

BUFG bufg_1x	( .I(clk1xdcm),		.O(clk1x) ) ;
BUFG bufg_2x	( .I(clk2xdcm),		.O(clk2x) ) ;
BUFG bufg_4x	( .I(clk4xdcm),		.O(clk4x) ) ;

Decoder #(
	.mult_width( 32 ),
	.pattern_width( 32 ) )
decoder (
	.clk( clk1x ),
	.mult( {fifo_dout[47:32],fifo_dout[63:48]} ),
	.pattern( fifo_dout[31:0] ),
	.rd_en( rd_en ),
	.dout( dec_out ));

Serializer8 ch0 (
	.clk1x(clk1x),
	.clk2x(clk2x),
	.clk4x(clk4x),
	.din(dec_out[7:0]),
	.dout(dout[0]));
	
Serializer8 ch1 (
	.clk1x(clk1x),
	.clk2x(clk2x),
	.clk4x(clk4x),
	.din(dec_out[15:8]),
	.dout(dout[1]));
	
Serializer8 ch2 (
	.clk1x(clk1x),
	.clk2x(clk2x),
	.clk4x(clk4x),
	.din(dec_out[23:16]),
	.dout(dout[2]));
	
Serializer8 ch3 (
	.clk1x(clk1x),
	.clk2x(clk2x),
	.clk4x(clk4x),
	.din(dec_out[31:24]),
	.dout(dout[3]));

endmodule